<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.7: http://docutils.sourceforge.net/" />
<title>前言导读</title>
<style type="text/css">

/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 6253 2010-03-02 00:24:53Z milde $
:Copyright: This stylesheet has been placed in the public domain.

Default cascading style sheet for the HTML output of Docutils.

See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/

/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
  border: 0 }

table.borderless td, table.borderless th {
  /* Override padding for "table.docutils td" with "! important".
     The right padding separates the table cells. */
  padding: 0 0.5em 0 0 ! important }

.first {
  /* Override more specific margin styles with "! important". */
  margin-top: 0 ! important }

.last, .with-subtitle {
  margin-bottom: 0 ! important }

.hidden {
  display: none }

a.toc-backref {
  text-decoration: none ;
  color: black }

blockquote.epigraph {
  margin: 2em 5em ; }

dl.docutils dd {
  margin-bottom: 0.5em }

/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
  font-weight: bold }
*/

div.abstract {
  margin: 2em 5em }

div.abstract p.topic-title {
  font-weight: bold ;
  text-align: center }

div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
  margin: 2em ;
  border: medium outset ;
  padding: 1em }

div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
  font-weight: bold ;
  font-family: sans-serif }

div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
  color: red ;
  font-weight: bold ;
  font-family: sans-serif }

/* Uncomment (and remove this text!) to get reduced vertical space in
   compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
  margin-bottom: 0.5em }

div.compound .compound-last, div.compound .compound-middle {
  margin-top: 0.5em }
*/

div.dedication {
  margin: 2em 5em ;
  text-align: center ;
  font-style: italic }

div.dedication p.topic-title {
  font-weight: bold ;
  font-style: normal }

div.figure {
  margin-left: 2em ;
  margin-right: 2em }

div.footer, div.header {
  clear: both;
  font-size: smaller }

div.line-block {
  display: block ;
  margin-top: 1em ;
  margin-bottom: 1em }

div.line-block div.line-block {
  margin-top: 0 ;
  margin-bottom: 0 ;
  margin-left: 1.5em }

div.sidebar {
  margin: 0 0 0.5em 1em ;
  border: medium outset ;
  padding: 1em ;
  background-color: #ffffee ;
  width: 40% ;
  float: right ;
  clear: right }

div.sidebar p.rubric {
  font-family: sans-serif ;
  font-size: medium }

div.system-messages {
  margin: 5em }

div.system-messages h1 {
  color: red }

div.system-message {
  border: medium outset ;
  padding: 1em }

div.system-message p.system-message-title {
  color: red ;
  font-weight: bold }

div.topic {
  margin: 2em }

h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
  margin-top: 0.4em }

h1.title {
  text-align: center }

h2.subtitle {
  text-align: center }

hr.docutils {
  width: 75% }

img.align-left, .figure.align-left, object.align-left {
  clear: left ;
  float: left ;
  margin-right: 1em }

img.align-right, .figure.align-right, object.align-right {
  clear: right ;
  float: right ;
  margin-left: 1em }

img.align-center, .figure.align-center, object.align-center {
  display: block;
  margin-left: auto;
  margin-right: auto;
}

.align-left {
  text-align: left }

.align-center {
  clear: both ;
  text-align: center }

.align-right {
  text-align: right }

/* reset inner alignment in figures */
div.align-right {
  text-align: left }

/* div.align-center * { */
/*   text-align: left } */

ol.simple, ul.simple {
  margin-bottom: 1em }

ol.arabic {
  list-style: decimal }

ol.loweralpha {
  list-style: lower-alpha }

ol.upperalpha {
  list-style: upper-alpha }

ol.lowerroman {
  list-style: lower-roman }

ol.upperroman {
  list-style: upper-roman }

p.attribution {
  text-align: right ;
  margin-left: 50% }

p.caption {
  font-style: italic }

p.credits {
  font-style: italic ;
  font-size: smaller }

p.label {
  white-space: nowrap }

p.rubric {
  font-weight: bold ;
  font-size: larger ;
  color: maroon ;
  text-align: center }

p.sidebar-title {
  font-family: sans-serif ;
  font-weight: bold ;
  font-size: larger }

p.sidebar-subtitle {
  font-family: sans-serif ;
  font-weight: bold }

p.topic-title {
  font-weight: bold }

pre.address {
  margin-bottom: 0 ;
  margin-top: 0 ;
  font: inherit }

pre.literal-block, pre.doctest-block {
  margin-left: 2em ;
  margin-right: 2em }

span.classifier {
  font-family: sans-serif ;
  font-style: oblique }

span.classifier-delimiter {
  font-family: sans-serif ;
  font-weight: bold }

span.interpreted {
  font-family: sans-serif }

span.option {
  white-space: nowrap }

span.pre {
  white-space: pre }

span.problematic {
  color: red }

span.section-subtitle {
  /* font-size relative to parent (h1..h6 element) */
  font-size: 80% }

table.citation {
  border-left: solid 1px gray;
  margin-left: 1px }

table.docinfo {
  margin: 2em 4em }

table.docutils {
  margin-top: 0.5em ;
  margin-bottom: 0.5em }

table.footnote {
  border-left: solid 1px black;
  margin-left: 1px }

table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
  padding-left: 0.5em ;
  padding-right: 0.5em ;
  vertical-align: top }

table.docutils th.field-name, table.docinfo th.docinfo-name {
  font-weight: bold ;
  text-align: left ;
  white-space: nowrap ;
  padding-left: 0 }

h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
  font-size: 100% }

ul.auto-toc {
  list-style-type: none }

</style>
</head>
<body>
<div class="document" id="id1">
<h1 class="title">前言导读</h1>

<!-- Preface
TODO:   Add references
        Proofread
Author: You Xu
Version: 0.1
Date:   Jan 30, 2011 -->
<p>某日，读罢编程珠玑，手不释卷，意犹未尽。突发狗尾续貂之念，遂有&quot;编程珠玑番外篇&quot;。既然是&quot;番外篇&quot;，选题大多都是原书之外的。两年前一开始写的时候，大多以历史八卦和趣事为主，信马由缰。后来选题渐渐无意识的收敛到了两个大的方面：</p>
<blockquote>
<ol class="arabic simple">
<li>从历史中找那些被人遗忘的编程珠玑;</li>
<li>推荐一些对效率很有帮助的编程工具和思维工具。</li>
</ol>
</blockquote>
<p>这两方面的文章成了&quot;番外篇&quot;的主题.</p>
<div class="section" id="id2">
<h1>一、追寻历史深处的编程珠玑</h1>
<p>在一次对图灵奖得主 Donald E. Knuth 的访谈中，当被问到为什么他要在名著 <em>The Art of Computer Programming</em> 里面不厌其烦的去追寻思想和概念的起源的时候，他风趣的说： (研究点历史) 会让程序设计变得受人尊敬，让人觉得编程不是一种转瞬即逝的技术，而是一门真正的技艺。其实，了解和探究程序设计的历史，捡起那些历史角落里的&quot;珠玑&quot;，除了能 &quot;让人尊敬&quot; ，以及满足人类天然的好奇心外，还至少有&quot;教&quot;和&quot;学&quot;两方面的好处.</p>
<p>从&quot;教&quot;的角度来说，探究历史中的编程珠玑，在教学上具有不可或缺的重要性。美国计算机学会 (ACM) 专门有个管计算机教学的工作组 SIGCSE，就曾经刊发过很多探究在教学中加入计算机科学发展史的教学内容。我不打算拾人牙慧，而是以我自己学习编程的经验来说明这一点.</p>
<p>我们知道，程序设计是一门实践的艺术。和理论世界相比，现实世界是复杂多变的，和实践打交道意味着理论上的有序，恒定，简明，有唯一解等理想的性质全部失去。取而代之的是复杂琐碎的细节，琢磨不透的变化，无处不在的特例，各执一词的最佳实践等等。也就是说，我们接触到的是&quot;割裂的现实&quot;(fragmented reality)，而非&quot;连贯的思想&quot;(train of thought)。此时，或揭示那些最佳实践的历史环境，那些发明和创新背后的思考轨迹，那些看似零碎的细节背后的一以贯之的指导思想，或探究把玩计算机编程发展史中的珠玑，或联系起看似毫不相关的知识，我们能够得到更加深刻的理解和思考，习得那些需要融会贯通才能得心应手地使用的知识。这都是我个人在自学编程时的切身体会.</p>
<p>教学相长。从&quot;学&quot;的角度来说，了解历史至少也有两方面的好处。首先，至少我们可以少犯前人犯过的错误。苹果主设计师 Andy 就曾经讲过，他犯过的最大的错误就是 32 bit clean。其实苹果不是第一个这样做的。早先在 IBM 的 Dec 设计中，就同样的错误。低估了摩尔定律的速度。比尔盖茨也曾说过，640k 够所有人，所以后来 DOS 系统不得不用各种各样的 trick 来绕过 640 k 的限制。这种情况到 Windows 95 才完全解决。我们平时编程的时候或许不需要做这么大的抉择，但编程和做 code review 的时候，知道前人犯过什么错误，至少可以少走弯路.</p>
<p>了解历史还可以帮我们真正理解系统的设计。我们都知道，程序设计没有教科书般的金科玉律，它总是设计的折衷，既有软件和硬件的折衷，又有与已有系统，已有环境的折衷。关于此，哲学家 Otto Neurath 曾经有过一个绝妙的比方： 重建一个浮在海上的船，在重建的时候还不能让它沉没。也就是说，任何一项设计，不管多么的革命性，或需要与之前兼容，或者符合使用习惯，或者满足某项需求，或解决当时某个现实的问题。所以，任何设计，都不可否认带着时代和环境的局限。为什么 FORTRAN 不支持递归，而 LISP 就支持。为什么 XUnit 这样的自动单元测试工具只在面向对象的 Smalltalk 中先出现。了解这些局限，一来可以仔细的考量设计的优缺点，了解了这些折衷，帮助我们更好的设计系统; 也能让我们不会去迷信设计，理解所有的设计和最佳实践都不是教条，而是环境的产物。因为没有银弹，我们能了解什么时候需要变通.</p>
<p>解读历史的文章如果不谨慎，极其容易走入两个误区。第一是自认为掌握了历史事件背后的规律，用一个事后诸葛亮的笔法去臧否历史。虽然历史或许有着背后的规律，但也充满了机遇和偶然。或许有考虑，但是，作者不是当时人，而只能随着现有资料去重现当年的历史和环境，寻找这些创新背后的故事。众所周知，伟大的创新往往出现前谁都没有想到，而出现后大家又觉得如此显然，而几乎所有关于历史的结论都是可以自圆其说的。在捡起这些历史上的珠玑给读者道来的时候，如果自诩掌握了历史的发展规律，用事后诸葛的方式来评点技术史，不免会把所有的创新写得很很显然，好像就是必然出现的。写书的欣欣然，读的欣欣然，其实除了满足智力优越感外并没有任何益处。众所周至，从历史事件中总结出规律是个极其简单的事情，几乎所有关于历史的结论都是可以自圆其说的。如果抓着历史来讲某种&quot;道理&quot;，历史就成了个任人打扮的小姑娘，于人毫无教益。然而，我们追寻历史的一大动机就是去发掘编程珠玑，因此总结一些有益的道理还是很有必要的。解读历史和臧否历史之间的间隔是如此之小，使我写作的时候不得不小心一些，至少要求忠实的列出当年的思维范式，历史环境。即使中间加入八卦为佐料，仍然要确保重要细节毫无偏差，以供读者从这些原始的素材中获得思考，而非经过我个人化解读后的版本。</p>
<p>第二个误区是只关心赢家的历史，把赢家的技术流派和思想当成编程珠玑，而把那些不出名的或影响力小的技术流派和思想忽略。这半个世纪以来，计算机程序设计的发展与技术和商业同时密不可分，其中成功的技术大多都获得了商业的成功。但显然商业成功和技术先进之间并不能划绝对等号。尤其是当我们把研究这些编程珠玑的出发点放在&quot;教&quot;和&quot;学&quot;两个方面的时候，就完全不能只看赢家。了解一些计算机体系结构的读者都知道，体系结构中有一本经典的教科书叫做 Computer Architecture： A Quantiative Approach (计算机体系结构--量化方法)，这本书是以 MIPS 而非 x86 架构讲解计算机体系结构。这本书选取 MIPS 当然和作者 Hennessy 和 Patterson 是 MIPS 的提出者有关。不过这本书，而不是其他基于 x86 体系的书成为体系结构方向经典的教科书，是和 MIPS 以及它代表的 RISC 系统适合教学密切相关的。而在商业领域，x86 体系几乎统治了桌面计算机市场，MIPS 几乎没有太大的作为。在这本书里，我希望向读者展示一个真实的，而非赢家的历史。</p>
</div>
<div class="section" id="id3">
<h1>二、程序员的效率工具</h1>
<p>除了探究历史中的珠玑外，本书中还有一部分文章是讨论一些可以提高程序员生产率(productivity) 的工具。</p>
<p>当我们谈及程序员的工具的时候，我们一般都会特制一样具体的软件。在这本书里面，我将不仅仅介绍软件工具，还介绍思维的工具。因为思维工具和软件工具都非常重要。甚至，按照 Kernighan 的话说，任何高效的工具都代替不了程序员自身清晰的思考。由此看思维工具的重要性不言而喻。从某种程度上来看，编程是一门解题 (Problem Solving) 的艺术。编程可以解读为解读的艺术的一个最好的说明，就是&lt;计算机程序设计艺术&gt;这多卷本的煌煌巨著了。翻看过这个系列书的人都了解，作者 Knuth 在书中的重点，根本不在代码怎么写上，而是在于一个看似很数学的问题怎么分析和解决。Dijkstra 也曾说过，计算机科学不是关于计算机，就像天文学不是关于望远镜一样。在这些知名计算机科学家眼里，计算机的全部用途，就是用来解决问题。</p>
<p>计算机作为解题工具在计算机科学中是再普遍不过的思想，几乎所有的计算机科学家都要经过很严格的解题能力训练，特别是数学和逻辑的训练。但是在软件开发领域，不是每个程序员都会经历这类的数学和逻辑的解题训练。 特别是面向对象技术和图形界面出现后，编程所需要的知识结构发生了变化，开发人员并不非要是计算机科学技术系的毕业生。因此，我们常常听到有种说法： X 学得不好照样能编程序，这里的 X 可以是高等数学，算法分析，编译原理等等任何一种计算机科学的基本知识。应该说，这样的说法有一定的事实根据，因为的确有些事务性的编程完全用不到太高深的知识。然而既然你在匆匆茫茫的人群中停下来阅读本书，就表示你的目标不是止步于一个普通的程序员。这时候， 这些基本的知识就显得极其重要。..。 这本书并不是这些基础知识的科普读物，你可以在这本书中读到的，将是带有作者个人偏好的书评和介绍，以及大量的书籍推荐。以我个人的经验来看，学会重要而基本知识需要长久的训练和持之以恒的实践，以及一本非常好的教科书。希望通过书中的这些文章，读者能够找到自己喜欢的书籍，充实自己的思维工具箱，最终成为卓越的程序员。</p>
<p>除了思维工具外，良好的软件工具也是高生产率的一个不可或却的因素。在这些文章中，我依然会带着强烈个人喜好的推荐我认为可以提升编程效率的平台，方法和思考。[本段没有完成]</p>
<p>在叙述历史，或者评论技术的文章中，为了增长阅读的趣味，文章中都有一些&quot;八卦&quot;的内容。原本发表在博客上的时候，这些奇闻轶事或者历史小故事是&quot;欺骗&quot;读者的一个好工具。这次编撰成书，为了保留原汁原味，我可以没有去掉这些&quot;八卦&quot;。这些&quot;八卦&quot;除特别注明外，一般都有出处，而非本人杜撰。写作这个系列文章的原始意图，是找寻读完&lt;编程珠玑&gt; 后意犹未尽的感觉，所以书中主题的选择，无一不带着我自身的喜好，也不可避免的带着我知识的局限。在本书中，我主观地选择了一些我认为是珠玑的素材，而把客观的判断和阅读交给读者。</p>
<p>是为序</p>
</div>
</div>
</body>
</html>
